
export function sortList(head: ListNode | null): ListNode | null {
    if (!head) return head;

    const dummyHead = new ListNode(0, head);
    let length = 0;
    let cur = head;
    while (cur) {
        length++;
        cur = cur.next!;
    }

    for (let subLen = 1; subLen < length; subLen = subLen * 2) {

        let prev = dummyHead;
        let next: ListNode|null = dummyHead.next;
        while (next) {
            // 切取 head1
            let head1 = next;
            let end1 = getEndNode(head1, subLen);
            next = end1.next;
            end1.next = null;
            // 切取 head2
            let head2: ListNode | null = null;
            if (next) {
                head2 = next;
                let end2 = getEndNode(head2!, subLen);
                next = end2.next;
                end2.next = null;
            } 
            // 合并 head
            prev.next = mergeList(head1, head2);
            // 将 prev 挪到合并列表后面
            while(prev.next) {
                prev = prev.next;
            }
        }
    }

    return dummyHead.next;
};

function mergeList (head1: ListNode|null, head2: ListNode|null): ListNode|null {
    const dummyHead = new ListNode(0, null);

    let cur = dummyHead;
    while (head1 && head2) {
        if (head1.val < head2.val) {
            cur.next = head1;
            head1 = head1.next;
        } else {
            cur.next = head2;
            head2 = head2.next;
        }
        cur = cur.next;
    }

    if (head1) {
        cur.next = head1;
    } else if (head2) {
        cur.next = head2;
    }

    return dummyHead.next;
}

function getEndNode (head: ListNode, length: number): ListNode {
    let i = 1; 
    let cur = head;
    while (i < length && cur.next) {
        cur = cur.next;
        i++;
    }
    return cur;
}

class ListNode {
    val: number
    next: ListNode | null
    constructor(val?: number, next?: ListNode | null) {
        this.val = (val===undefined ? 0 : val)
        this.next = (next===undefined ? null : next)
    }
}

export function array2NodeList (nums: number[]) {
    const dummyHead = new ListNode(0);
    let cur = dummyHead;
    for (let i = 0; i < nums.length; i++) {
        const node = new ListNode(nums[i]);
        cur.next = node;
        cur = cur.next;
    }
    return dummyHead.next;
}

export function nodeList2Array (head: ListNode) {
    let arr: number[] = [];
    let cur = head;
    while (cur) {
        arr.push(cur.val);
        cur = cur.next!;
    }
    return arr; 
}